﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using LiteDb;
using Newtonsoft.Json;
using DidaManager.Native.Network;
using Newtonsoft.Json.Linq;
using DidaManager.Models;

namespace DidaManager.Native.Network
{
    public class NetworkManager
    {
        private readonly DeviceSearchUdpServer _deviceSearchServer;
        public readonly OrayManager _orayManager;

        public NetworkManager()
        {
            _deviceSearchServer = new DeviceSearchUdpServer();
            _orayManager = new OrayManager();
           
           // 在运行程序config目录下加载mqtt_config.json文件
           MqttUIConfig.LoadFromJsonFile(Path.Combine(AppContext.BaseDirectory, "config", "mqtt_config.json"));

            // 在运行程序config目录下加载hj212_system_type.json文件
            var filePath = Path.Combine(AppContext.BaseDirectory, "config", "hj212_system_type.json");
            HJ212SystemType.LoadFromJsonFile(filePath);
        }

        public string? GetDownloadUrl(object param)
        {
            // 获取ip和port
            string ip = string.Empty;
            uint port = 0;
            GetIPAndPort(param, out ip, out port);

            var url = NetworkConfig.Instance.GetDownloadUrl();
            if (string.IsNullOrEmpty(url))
            {
                return string.Empty;
            }

            return ComposeUrl(url, ip, port);
        }

        public string GetLoginUrl()
        {
            var url = NetworkConfig.Instance.GetLoginUrl();
            if (string.IsNullOrEmpty(url))
            {
                return string.Empty;
            }

            return url;
        }

        /// <summary>
        /// 检查设备是否在线
        /// </summary>
        /// <param name="ip">ip</param>
        /// <param name="port">port</param>
        /// <returns>是否在线</returns>
        public bool IsDeviceOnline(string ip, uint port)
        {
            if (string.IsNullOrEmpty(ip))
            {
                throw new ArgumentNullException(nameof(ip), "IP 地址不能为空");
            }

            var url = NetworkConfig.Instance.GetConnectUrl();
            if (string.IsNullOrEmpty(url))
            {
                return false; // Handle null or empty URL gracefully
            }

            var composedUrl = ComposeUrl(url, ip, port);
            if (!CheckUrlValid(composedUrl))
            {
                return false;
            }

            var response = HttpManager.Get(composedUrl);
            return response.StatusCode == System.Net.HttpStatusCode.OK;
        }
        
        private void GetIPAndPort(object param, out string ip, out uint port)
        {
            if (param == null)
            {
                throw new ArgumentNullException(nameof(param), "参数不能为空");
            }            
            ip = string.Empty;
            port = 0;
            var jsonString = param.ToString()!;
            var jObject = JObject.Parse(jsonString);
            // 提取基本字段
            if (jObject.TryGetValue("ip", out var ipToken))
            {
                ip = ipToken.ToString();
            }

            if (jObject.TryGetValue("port", out var portToken))
            {
                port = Convert.ToUInt32(portToken);
            }
        }

        /// <summary>
        /// 处理适配器连接
        /// </summary>
        /// <param name="param">连接参数</param>
        /// <returns>连接结果</returns>
        public object HandleAdapterConnect(object param)
        {
            try
            {
                // 检查参数是否为空
                if (param == null)
                {
                    return ApiResponse.Fail("参数不能为空");
                }

                // 获取ip和port
                string ip = string.Empty;
                uint port = 0;
                GetIPAndPort(param, out ip, out port);

                var isOnline = IsDeviceOnline(ip, port);
                return ApiResponse.Success(isOnline);
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"适配器连接失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取网关设备列表
        /// </summary>
        public object GetGateWayDeviceList(object param)
        {
            try
            {
                // 检查参数是否为空
                if (param == null)
                {
                    return ApiResponse.Fail("参数不能为空");
                }

                return HandleSearchDevice(param);
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"获取网关设备列表失败: {ex.Message}");
            }
        }


        /// <summary>
        /// 组合url
        /// </summary>
        /// <param name="url">url</param>
        /// <param name="ip">ip</param>
        /// <param name="port">port</param>
        /// <returns>组合后的url</returns>
        public string ComposeUrl(string url, string ip, uint port)
        {
            return $"http://{ip}:{port}{url}";
        }

        /// <summary>
        /// 检查url是否有效
        /// </summary>
        /// <param name="url">url</param>
        /// <returns>是否有效</returns>
        public bool CheckUrlValid(string url)
        {
            // 需要判断url是否是有效的url
            return Uri.TryCreate(url, UriKind.Absolute, out _);
        }

        /// <summary>
        /// 处理设备搜索请求
        /// </summary>
        /// <param name="param">搜索参数</param>
        /// <returns>搜索结果</returns>
        public object HandleSearchDevice(object param)
        {
            try
            {
                // 检查参数是否为空
                if (param == null)
                {
                    return ApiResponse.Fail("参数不能为空");
                }

                var searchParam = ParseSearchParam(param);
                
                // 异步搜索设备但同步返回结果
                var searchTask = _deviceSearchServer.SearchDevicesAsync(
                    searchParam.BroadcastMessage,
                    searchParam.BroadcastPort,
                    searchParam.ListenPort
                );

                // 等待搜索完成
                var devices = searchTask.GetAwaiter().GetResult();

                var jsonString = JsonConvert.SerializeObject(devices);
                return ApiResponse.Success(jsonString);
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"设备搜索失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 停止设备搜索
        /// </summary>
        public void StopDeviceSearch()
        {
            _deviceSearchServer.StopSearch();
        }

        /// <summary>
        /// 获取已发现的设备
        /// </summary>
        /// <returns>设备列表</returns>
        public List<DeviceInfo> GetDiscoveredDevices()
        {
            return _deviceSearchServer.GetDiscoveredDevices();
        }

        /// <summary>
        /// 清除已发现的设备
        /// </summary>
        public void ClearDiscoveredDevices()
        {
            _deviceSearchServer.ClearDiscoveredDevices();
        }

        /// <summary>
        /// 解析搜索参数
        /// </summary>
        /// <param name="param">参数对象</param>
        /// <returns>搜索参数</returns>
        private SearchParam ParseSearchParam(object param)
        {
            var defaultParam = new SearchParam
            {
                BroadcastMessage = "DEVICE_DISCOVERY",
                BroadcastPort = 8888,
                ListenPort = 0
            };

            if (param == null)
                return defaultParam;

            try
            {
                var jsonString = param.ToString();
                if (string.IsNullOrEmpty(jsonString))
                    return defaultParam;

                var searchParam = JsonConvert.DeserializeObject<SearchParam>(jsonString);
                if (searchParam == null)
                    return defaultParam;
                // 需要把jsonString中的BroadcastMessage转成json字符串，字段是"Search"
                var searchJsonString = JsonConvert.SerializeObject(new { Search = searchParam.BroadcastMessage });
                searchParam.BroadcastMessage = searchJsonString;
                return searchParam ?? defaultParam;
            }
            catch
            {
                // 如果解析失败，返回默认参数
                return defaultParam;
            }
        }

        /// <summary>
        /// 通过网络下载配置
        /// </summary>
        public object DownloadConfigViaNetwork(object param)
        {
            try
            {
                // 检查参数是否为空
                if (param == null)
                {
                    return ApiResponse.Fail("参数不能为空");
                }

                // 获取ip和port
                string ip = string.Empty;
                uint port = 0;
                GetIPAndPort(param, out ip, out port);
                
                // 获取下载url
                var url = GetDownloadUrl(param);
                if (string.IsNullOrEmpty(url))
                {
                    return ApiResponse.Fail("下载url为空");
                }
                var composedUrl = ComposeUrl(url, ip, port);
                if (!CheckUrlValid(composedUrl))
                {
                    return ApiResponse.Fail("下载url无效");
                }
                // 发送下载请求
                var response = HttpManager.Get(composedUrl);
                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    return ApiResponse.Success("网络下载成功");
                }
                else
                {
                    return ApiResponse.Fail("网络下载失败");
                }
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"网络下载异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 测试网络连接
        /// </summary>
        public object TestNetworkConnection(object param)
        {
            try
            {
                // 检查参数是否为空
                if (param == null)
                {
                    return ApiResponse.Fail("参数不能为空");
                }

                // 获取ip和port
                string ip = string.Empty;
                uint port = 0;
                GetIPAndPort(param, out ip, out port);
                
                var isOnline = IsDeviceOnline(ip, port);
                return ApiResponse.Success(isOnline);
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"网络连接测试失败: {ex.Message}");
            }
        }

        public object GetHJ212SystemType(object param)
        {
            try
            {
                // 检查参数是否为空
                var systemTypeNames = HJ212SystemType.GetAllSystemTypeNames();
                var jsonString = JsonConvert.SerializeObject(systemTypeNames);
                return ApiResponse.Success(jsonString);
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail(ex.Message);
            }
        }

        public object RestartGateway(object param)
        {
            try
            {
                // 检查参数是否为空
                if (param == null)
                {
                    return ApiResponse.Fail("参数不能为空");
                }

                // 获取ip和port
                string ip = string.Empty;
                uint port = 0;
                GetIPAndPort(param, out ip, out port);            
                // 重启网关url
                var url = NetworkConfig.Instance.GetRestartUrl();
                if (string.IsNullOrEmpty(url))
                {
                    return ApiResponse.Fail("重启网关url为空");
                }
                var composedUrl = ComposeUrl(url, ip, port);
                if (!CheckUrlValid(composedUrl))    
                {
                    return ApiResponse.Fail("重启网关url无效");
                }
                // 发送重启网关请求
                var response = HttpManager.Get(composedUrl);
                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    return ApiResponse.Success("重启网关成功");
                }
                else
                {
                    return ApiResponse.Fail("重启网关失败");
                }
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"重启网关异常: {ex.Message}");
            }
        }

        public object ModuleChunkUpdate(object param)
        {
            try
            {
                // 检查参数是否为空
                if (param == null)
                {
                    return ApiResponse.Fail("参数不能为空");
                }

                // 解析参数
                string filePath = string.Empty;
                
                var jsonString = param.ToString()!;
                var jObject = JObject.Parse(jsonString);
                
                // 提取文件路径
                if (jObject.TryGetValue("filepath", out var filePathToken))
                {
                    filePath = filePathToken.ToString();
                }
                else
                {
                    return ApiResponse.Fail("缺少filePath参数");
                }

                // 检查文件是否存在
                if (!System.IO.File.Exists(filePath))
                {
                    return ApiResponse.Fail($"文件不存在: {filePath}");
                }

                // 获取ip和port
                string ip = string.Empty;
                uint port = 0;
                GetIPAndPort(param, out ip, out port);

                // 模块分块更新url
                var moduleChunkUpdateUrl = NetworkConfig.Instance.GetModuleChunkUpdateUrl();
                if (string.IsNullOrEmpty(moduleChunkUpdateUrl))
                {
                    return ApiResponse.Fail("模块分块更新url为空");
                }

                var composedUrl = ComposeUrl(moduleChunkUpdateUrl, ip, port);
                if (!CheckUrlValid(composedUrl))
                {
                    return ApiResponse.Fail("模块分块更新url无效");
                }

                var optionsResponse = HttpManager.Options(composedUrl, "", "token");
                // 判断是否有返回值(非hj212网关不需要更新)
                if (!optionsResponse.IsSuccessful)
                {
                    return ApiResponse.Success("非hj212网关不需要更新");
                }
                // 使用模块分块更新功能
                var response = HttpManager.ModuleChunkUpdate(composedUrl, filePath);
                
                if (response.IsSuccessful)
                {
                    return ApiResponse.Success("模块分块更新成功");
                }
                else
                {
                    return ApiResponse.Fail($"模块分块更新失败: {response.Content}");
                }
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"模块分块更新异常: {ex.Message}");
            }
        }

        public object UpdateNormalFirmware(object param)
        {
            try
            {
                // 检查参数是否为空
                if (param == null)
                {
                    return ApiResponse.Fail("参数不能为空");
                }

                // 解析参数
                string filePath = string.Empty;
                string updateAreaName = "update";
                
                var jsonString = param.ToString()!;
                var jObject = JObject.Parse(jsonString);
                
                // 提取文件路径
                if (jObject.TryGetValue("filepath", out var filePathToken))
                {
                    filePath = filePathToken.ToString();
                }
                else
                {
                    return ApiResponse.Fail("缺少filePath参数");
                }

                // 检查文件是否存在
                if (!System.IO.File.Exists(filePath))
                {
                    return ApiResponse.Fail($"文件不存在: {filePath}");
                }

                // 获取ip和port
                string ip = string.Empty;
                uint port = 0;
                GetIPAndPort(param, out ip, out port);

                // 更新固件url
                var url = NetworkConfig.Instance.GetFirewareUrl();
                if (string.IsNullOrEmpty(url))
                {
                    return ApiResponse.Fail("更新固件url为空");
                }

                var composedUrl = ComposeUrl(url, ip, port);
                if (!CheckUrlValid(composedUrl))
                {
                    return ApiResponse.Fail("更新固件url无效");
                }

                // 使用新的文件上传功能
                var response = HttpManager.FileUpload(composedUrl, filePath, updateAreaName);
                
                if (response.IsSuccessful)
                {
                    return ApiResponse.Success("更新固件成功");
                }
                else
                {
                    return ApiResponse.Fail($"更新固件失败: {response.Content}");
                }
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"更新固件异常: {ex.Message}");
            }
        }

        public object UpdateFirmware(object param)
        {
            try
            {
                // 检查参数是否为空
                if (param == null)
                {
                    return ApiResponse.Fail("参数不能为空");
                }

                // 解析参数
                string filePath = string.Empty;
                string gatewayType = string.Empty;
                
                var jsonString = param.ToString()!;
                var jObject = JObject.Parse(jsonString);
                
                // 提取文件路径
                if (jObject.TryGetValue("filepath", out var filePathToken))
                {
                    filePath = filePathToken.ToString();
                }
                else
                {
                    return ApiResponse.Fail("缺少filePath参数");
                }

                // 检查文件是否存在
                if (!System.IO.File.Exists(filePath))
                {
                    return ApiResponse.Fail($"文件不存在: {filePath}");
                }

                if (jObject.TryGetValue("gatewayType", out var gatewayTypeToken))
                {
                    gatewayType = gatewayTypeToken.ToString();
                }
                else
                {
                    return ApiResponse.Fail("缺少gatewayType参数");
                }   

                if (gatewayType == "HJ212")
                {
                    return ModuleChunkUpdate(param);
                }
                else
                {
                    return UpdateNormalFirmware(param);
                }

            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"更新固件异常: {ex.Message}");
            }
        }

        public object UpdateToServer(object param)
        {
            try
            {
                // 检查参数是否为空
                if (param == null)
                {
                    return ApiResponse.Fail("参数不能为空");
                }

                return ApiResponse.Success("更新到服务器成功");
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"更新到服务器失败: {ex.Message}");
            }
        }

        public object UpdateToDevice(object param)
        {
            try
            {
                // 检查参数是否为空
                if (param == null)
                {
                    return ApiResponse.Fail("参数不能为空");
                }

                return ApiResponse.Success("更新到设备成功");
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"更新到设备失败: {ex.Message}");
            }
        }

        public object GetDeviceUpdateStatus(object param)
        {
            try
            {
                // 检查参数是否为空
                if (param == null)
                {
                    return ApiResponse.Fail("参数不能为空");
                }

                return ApiResponse.Success("获取设备更新状态成功");
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"获取设备更新状态失败: {ex.Message}");
            }
        }

        public object ReadRemoteMonitorVariant(object param)
        {
            return ReadWriteRemoteMonitorVariant(param);
        }
        
        public object WriteRemoteMonitorVariant(object param)
        {
            return ReadWriteRemoteMonitorVariant(param);
        }

        public object ReadWriteRemoteMonitorVariant(object param)
        {
            try
            {
                var jsonString = param.ToString()!;
                var jObject = JObject.Parse(jsonString);                
                
                // 提取Vars部分
                if (!jObject.TryGetValue("Vars", out var varsToken) || !(varsToken is JObject varsObj))
                {
                    return ApiResponse.Fail("请求中缺少Vars部分");
                }

                // 提取Params部分
                if (!jObject.TryGetValue("Params", out var paramsToken) || !(paramsToken is JObject paramsObj))
                {
                    return ApiResponse.Fail("请求中缺少Params部分");
                }

                // 从Params中获取ip和port
                string ip = paramsObj["ip"]?.ToString() ?? string.Empty;
                uint port = paramsObj["port"]?.ToObject<uint>() ?? 0;

                if (string.IsNullOrEmpty(ip) || port == 0)
                {
                    return ApiResponse.Fail("IP或端口无效");
                }

                var url = NetworkConfig.Instance.GetTestVariableUrl();
                if (string.IsNullOrEmpty(url))
                {
                    return ApiResponse.Fail("读取/写入变量url为空");
                }

                var composedUrl = ComposeUrl(url, ip, port);
                if (!CheckUrlValid(composedUrl))
                {
                    return ApiResponse.Fail("读取/写入变量url无效");
                }

                // 直接使用Vars部分的内容作为请求体
                var response = HttpManager.Post(composedUrl, varsObj.ToString(Formatting.None));
                if (response.StatusCode != System.Net.HttpStatusCode.OK)
                {
                    return ApiResponse.Fail($"读取/写入变量失败: {response.ErrorException}");
                }
                return ApiResponse.Success(response.Content, "读取/写入变量成功");
            }
            catch (Exception ex)
            {
                return ApiResponse.Fail($"读取/写入变量失败: {ex.Message}");
            }
        }

    }

    /// <summary>
    /// 设备搜索参数
    /// </summary>
    public class SearchParam
    {
        public string BroadcastMessage { get; set; } = "DEVICE_DISCOVERY";
        public int BroadcastPort { get; set; } = 8888;
        public int ListenPort { get; set; } = 0;
    }
}
